package com.augurit.wf.common.util;

import java.sql.Timestamp;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springside.modules.orm.Page;

import com.augurit.common.entity.SysMetaColumn;
import com.augurit.common.util.lang.CollectionUtils;
import com.augurit.common.util.lang.DateUtils;
import com.augurit.common.util.lang.StringUtils;
import com.augurit.wf.bi.web.form.WfViewConfigForm;
import com.augurit.wf.common.web.WfBusPropertyConfig;

public class ViewConfigCompiler {

	public static final String PROP_SEPARATOR = ",";
	public static final String BUS_ENTITY_ALIAS = "bus";
	public static final String RANGE_START_FLAG = "Start";
	public static final String RANGE_END_FLAG = "End";
	public static final String NULL_VAR_FLAG = "[NULL]";
	public static final String PARAM_VAR_FLAG = ":";
	
	
	public static Date getMaxDate(){
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, 2099);
		cal.set(Calendar.MONTH, 12);
		return cal.getTime();
	}
	
	public static Date getMinDate(){
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, 1900);
		cal.set(Calendar.MONTH, 1);
		return cal.getTime();
	}
	
	public static void clearUseLessParam(Map<String, String> params){
		if(params != null && params.size() > 0){
			//清除无用参数
			params.remove("start");
			params.remove("limit");
			params.remove("sort");
			params.remove("dir");
			params.remove("groupBy");
			params.remove("groupDir");
			params.remove("template.templateCode");
		}
	}
	
//	public static void addTimeProgressProp(Page page){
//		if(page != null && page.getResult() != null && page.getResult().size() > 0){
//			List<Object[]> result = new ArrayList();
//			
//			List<Object[]> list = page.getResult();
//			for(Object[] objs : list){
//				
//				Timestamp create = (Timestamp)objs[0];
//				Timestamp duedate = (Timestamp)objs[1];
//				long now = Calendar.getInstance().getTimeInMillis();
//				
//				
//				float percent = -1;
//				
//				if(duedate != null){
//					float l1 = (float)now - create.getTime();
//					float l2 = (float)duedate.getTime() - create.getTime();
//					percent = l1/l2 * 100;
//				}
//
//				Object[] newObjs = new Object[objs.length+1];
//				newObjs[0] = (int)percent;
//				
//				for(int i=0; i<objs.length; i++){
//					newObjs[i+1] = objs[i];
//				}
//				
//				result.add(newObjs);
//			}
//			
//			page.setResult(result);
//		}
//	}
	
	/**
	 * 解析WHERE语句并生成符合实际查询条件的WHERE子句
	 * @param whereCondition
	 * @param whereLogic
	 * @param objParams 包含实际查询字段和查询值的MAP
	 * @return
	 */
	public static String parseWhereClause(String whereCondition, String whereLogic, Map<String, Object> objParams){
		if(whereCondition != null && whereCondition.trim().length() > 0
				&& objParams != null && objParams.size() > 0){
			
			// 替换变量标识
			String noVarFlagCondition = whereCondition;
			while(existVarFlag(noVarFlagCondition)){
				noVarFlagCondition = replaceVarFlag(noVarFlagCondition, objParams);
			}			
			
			//去除NULL变量标识的子句
			String[] clauses = noVarFlagCondition.split(whereLogic);
			List<String> noNullVarFlagClauseList = removeNullVarFlagClause(clauses);
			
			//检索出有实际查询值的子句
			String[] validQueryKeys = CollectionUtils.toStringArray(objParams.keySet());
			List<String> validClauseList = getValidClauseList(validQueryKeys, noNullVarFlagClauseList);

			return StringUtils.convertStringListToString(validClauseList, whereLogic);
		}
		return null;
	}
	
	/**
	 * 去除空变量标识的子句
	 */
	private static List<String> removeNullVarFlagClause(String[] clauses){
		if(clauses != null && clauses.length > 0){
			List<String> result = new ArrayList();
			
			for(String clause : clauses){
				if(clause.trim().indexOf(NULL_VAR_FLAG) < 0){
					result.add(clause);
				}
			}
			
			return result;
		}
		return null;
	}
	
	private static List<String> getValidClauseList(String[] validQueryKeys, List<String> notNullVarFlagClauseList){
		if(validQueryKeys != null && validQueryKeys.length > 0 
				&& notNullVarFlagClauseList != null && notNullVarFlagClauseList.size() > 0){
			
			List<String> result = new ArrayList();
			
			for(String noNullVarFlagClause : notNullVarFlagClauseList){
				if(noNullVarFlagClause.indexOf(PARAM_VAR_FLAG) < 0 || containValidQueryKey(noNullVarFlagClause, validQueryKeys)){
					result.add(noNullVarFlagClause);
				}
			}
			
			return result;
		}
		return null;
	}
	
	private static boolean containValidQueryKey(String notNullVarFlagClause, String[] validQueryKeys){
		if(notNullVarFlagClause != null && validQueryKeys != null && validQueryKeys.length > 0){
			for(String validQueryKey : validQueryKeys){
				if(notNullVarFlagClause.indexOf(PARAM_VAR_FLAG + validQueryKey) > 0){
					return true;
				}
			}
		}
		return false;
	}
	
	private static String replaceVarFlag(String condition, Map<String, Object> objParams){
		String varFlag = findVarFlagName(condition);
		Object varValue = objParams.get(varFlag);
		
		if(varValue != null)
			return condition.replace("{"+varFlag+"}", varValue.toString());
		else
			return condition.replace("{"+varFlag+"}", "[NULL]");
	}
	
	private static String findVarFlagName(String clause){
		int start = clause.indexOf("{");
		int end = clause.indexOf("}");
		return clause.substring(start+1, end);
	}
	
	private static boolean existVarFlag(String condition){
		if(condition != null && condition.trim().length() > 0){
			
			int start = condition.indexOf("{");
			int end = condition.indexOf("}");
			
			if(start < end)
				return true;
		}
		return false;
	}
	
	public static String findBusEntityName(String selectEntities){
		if(selectEntities != null && selectEntities.trim().length() > 0){
			String[] entities = selectEntities.split(PROP_SEPARATOR);
			for(String entity : entities){
				int pos = entity.indexOf(" bus");
				if(pos > 0){
					return entity.substring(0, pos).trim();
				}
			}
		}
		return null;
	}
	
	public static Map<String, Object> convertToObjectMap(Map<String, String> params, List<SysMetaColumn> columns){
		if(params != null && params.size() > 0){
			Map<String, Object> result = new HashMap();

			if(columns != null && columns.size() > 0){
				for(SysMetaColumn column : columns){
					
					if(column.getColumnType().equals("date")){
					
						String startDate = params.get(column.getColumnName() + RANGE_START_FLAG);
						String endDate = params.get(column.getColumnName() + RANGE_END_FLAG);
						
						if((startDate != null && startDate.trim().length() > 0)
								&& (endDate != null && endDate.trim().length() > 0)){
							
							try {
								result.put(column.getColumnName() + RANGE_START_FLAG, 
										DateUtils.stringToDate(convertToValidExtDateTimeFormat(startDate)));
								
								result.put(column.getColumnName() + RANGE_END_FLAG, 
										DateUtils.stringToDate(convertToValidExtDateTimeFormat(endDate)));
								
							} catch (ParseException e) {
								e.printStackTrace();
							}
						}						
						else if((startDate != null && startDate.trim().length() > 0)
								&& (endDate == null || endDate.trim().length() == 0)){
							
							try {
								result.put(column.getColumnName() + RANGE_START_FLAG, 
										DateUtils.stringToDate(convertToValidExtDateTimeFormat(startDate)));
								
								result.put(column.getColumnName() + RANGE_END_FLAG, getMaxDate());
								
							} catch (ParseException e) {
								e.printStackTrace();
							}
						}
						else if((startDate == null || startDate.trim().length() == 0)
								&& (endDate != null && endDate.trim().length() > 0)){
							
							try {
								result.put(column.getColumnName() + RANGE_START_FLAG, getMinDate());
								
								result.put(column.getColumnName() + RANGE_END_FLAG, 
										DateUtils.stringToDate(convertToValidExtDateTimeFormat(endDate)));

							} catch (ParseException e) {
								e.printStackTrace();
							}
						}
					}
					
					else{
						String value = params.get(column.getColumnName());
						if(value != null && value.trim().length() > 0)
							result.put(column.getColumnName(), value);
					}
				}
			}
			
			return result;
		}else
			return null;
	}
	
	public static String convertToValidExtDateTimeFormat(String datetimeStr){
		if(datetimeStr != null && datetimeStr.trim().length() > 0){
			return datetimeStr.replace("T", " ");
		}else
			return null;
	}
	
	public static Map<String, String> convertToParamMap(Map<String, String[]> params){
		if(params != null && params.size() > 0){
			Map<String, String> result = new HashMap();
			
			Iterator<Map.Entry<String, String[]>> it = params.entrySet().iterator();
			while(it.hasNext()){
				Map.Entry<String, String[]> entry = it.next();
				result.put(entry.getKey(), convertStringArrayToStr(entry.getValue()));
			}
			
			return result;
		}
		return null;
	}
	
	public static String convertStringArrayToStr(String[] params){
		if(params != null && params.length > 0){
			StringBuffer sb = new StringBuffer();
			for(int i=0; i<params.length; i++){
				String param = params[i];
				if(param != null && param.trim().length() > 0){
					sb.append(param.trim());
				}
				if(i < params.length - 1)
					sb.append(PROP_SEPARATOR);
			}
			return sb.toString();
		}
		return "";
	}
	
	public static String convertToMetaQueryClause(Map<String, SysMetaColumn> propMap){
		if(propMap != null && propMap.size() > 0){
			String result = " and (";
				
			Iterator<Map.Entry<String, SysMetaColumn>> it = propMap.entrySet().iterator();
			while(it.hasNext()){
				Map.Entry<String, SysMetaColumn> entry = it.next();
				String[] arr = entry.getKey().split("\\.");
				result += "(t.tableName='" + arr[0] + "' and c.columnName='" + arr[1] + "')";
				result += " or ";
			}
			
			//去除最后的“or”字符串
			int lastPos = result.lastIndexOf(" or ");
			result = result.substring(0, lastPos);
			
			result += ")";
				
			return result;
		}else
			return null;
	}
	
	public static String getOnlyPropertyName(String keyProperty){
		if(keyProperty != null && keyProperty.trim().length() > 0){
			return keyProperty.split("\\.")[1];
		}else
			return null;
	}
	
	public static List<WfBusPropertyConfig> convertWfBusPropertyConfig(List<SysMetaColumn> columns){
		if(columns != null && columns.size() > 0){
			List<WfBusPropertyConfig> result = new ArrayList();
			
			for(SysMetaColumn column : columns){
				result.add(convertWfBusPropertyConfig(column));
			}
			
			return result;
		}else
			return null;
	}
	
	public static WfBusPropertyConfig convertWfBusPropertyConfig(SysMetaColumn column){
		if(column != null){
			WfBusPropertyConfig property = new WfBusPropertyConfig();
			property.setPropertyName(column.getColumnName());
			property.setPropertyComment(column.getColumnComments());
			property.setPropertyType(column.getColumnType());
			return property;
		}else
			return null;
	}
	
	public static List<SysMetaColumn> convertToMetaColumnList(Map<String, SysMetaColumn> map){
		if(map != null && map.size() > 0){
			List<SysMetaColumn> result = new ArrayList<SysMetaColumn>();
			
			Iterator<Map.Entry<String, SysMetaColumn>> it = map.entrySet().iterator();
			while (it.hasNext()) {
				SysMetaColumn entity = it.next().getValue();
				if(entity != null)
					result.add(entity);
			}
			return result;
		}else
			return null;
	}
	
	public static String upperCaseFirstChar(String str){
		if(str != null && str.trim().length() > 0){
			return str.substring(0, 1).toUpperCase() + str.substring(1);
		}else
			return null;
	}
	
	public static String lowerCaseFirstChar(String str){
		if(str != null && str.trim().length() > 0){
			return str.substring(0, 1) + str.substring(1).toLowerCase();
		}else
			return null;
	}
	
	public static String convertToEntityName(String tableName){
		if(tableName != null && tableName.trim().length() > 0){
			String result = "";
			String[] array = tableName.split("_");
			for(String s : array){
				result += upperCaseFirstChar(s.toLowerCase());
			}
			return result;
		}else
			return null;
	}
	
	public static String convertToPropertyName(String columnName){
		if(columnName != null && columnName.trim().length() > 0){
			String result = "";
			String[] array = columnName.split("_");
			for(int i=0; i<array.length; i++){
				if(i == 0)
					result += array[i].toLowerCase();
				else	
					result += upperCaseFirstChar(array[i].toLowerCase());
			}
			return result;
		}else
			return null;
	}
	
	public static String addSortClause(String groupBy, String groupDir, String sort, String dir, WfViewConfigForm viewConfig){
		String result = "";
		
		if((groupBy != null && groupBy.trim().length() > 0) 
				|| (sort != null && sort.trim().length() > 0)){
			
			result = " order by ";
			
			String wholeGroupByPropertyName = findWholePropertyName(viewConfig.getListProperties(), groupBy);
			if(wholeGroupByPropertyName != null)
				result += wholeGroupByPropertyName + " " + (groupDir == null ? "" : groupDir);
			
			String wholeSortPropertyName = findWholePropertyName(viewConfig.getListProperties(), sort);
			if(wholeSortPropertyName != null)
				result += (wholeGroupByPropertyName == null ? "" : ",") + wholeSortPropertyName + " " + (dir == null ? "" : dir);
		}
		else if(viewConfig.getOrderProperty() != null && viewConfig.getOrderProperty().trim().length() > 0)
			result = " order by " + viewConfig.getOrderProperty() + " " + (viewConfig.getOrderby() == null ? "" : viewConfig.getOrderby());

		return result;
	}
	
	private static String findWholePropertyName(String listProperties, String propertyName){
		if(listProperties != null && listProperties.trim().length() > 0
				&& propertyName != null && propertyName.trim().length() > 0){
			String[] entities = listProperties.split(PROP_SEPARATOR);
			for(String entity : entities){
				if(entity.indexOf("." + propertyName) > 0){
					return entity;
				}
			}
		}
		return null;
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

	}

}
